package org.infodavid.common.model.impl;

import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.infodavid.common.IBuilder;
import org.infodavid.common.annotations.AImplementation;
import org.infodavid.common.annotations.AImplementation.ERuntime;
import org.infodavid.common.impl.ObjectFactoryImpl;
import org.infodavid.common.impl.ObjectFactoryImpl.BuilderImpl;
import org.infodavid.common.model.IApplicationSettings;
import org.infodavid.common.model.IContentInfo;
import org.infodavid.common.model.IDocument;
import org.infodavid.common.model.IDocumentCategory;
import org.infodavid.common.model.IDocumentVersion;
import org.infodavid.common.model.IGenericPropertiesMap;
import org.infodavid.common.model.IGenericProperty;
import org.infodavid.common.model.IImageData;
import org.infodavid.common.model.IOrganization;
import org.infodavid.common.model.IPermissions;
import org.infodavid.common.model.IPerson;
import org.infodavid.common.model.ITemplate;
import org.infodavid.common.model.ITemplateCategory;
import org.infodavid.common.model.ITemplateVersion;
import org.infodavid.common.model.IUser;
import org.infodavid.common.model.IUserConnection;
import org.infodavid.common.model.IUserGroup;
import org.infodavid.common.model.IUserSession;
import org.infodavid.common.model.ModelFactory;
import org.infodavid.common.model.components.IEMail;
import org.infodavid.common.model.components.IGeoLocation;
import org.infodavid.common.model.components.ILocation;
import org.infodavid.common.model.components.IOwnerDetails;
import org.infodavid.common.model.components.IPhone;
import org.infodavid.common.model.components.IUri;
import org.infodavid.common.model.security.IAccessControlEntry;
import org.infodavid.common.model.security.IAccessControlList;
import org.infodavid.common.model.security.ISecuredObjectIdentifier;
import org.infodavid.common.model.security.ISecurityIdentifier;
import org.infodavid.common.persistence.IBasicDataObject;

/**
 * The Class DefaultModelFactory.
 */
@AImplementation(value = ModelFactory.class, runtime = ERuntime.DEFAULT)
public class DefaultModelFactory extends org.infodavid.common.model.ModelFactory {

	/** The logger. */
	private static final Log LOGGER = LogFactory.getLog(DefaultModelFactory.class);

	/** The delegate. */
	private final ObjectFactoryImpl<IBasicDataObject> delegate =
	    new ObjectFactoryImpl<IBasicDataObject>();

	/**
	 * Constructor.
	 * @throws NoSuchMethodException The exception
	 */
	protected DefaultModelFactory() throws NoSuchMethodException {
		super();

		if (LOGGER.isDebugEnabled()) {
			LOGGER.debug("Adding mappings of concrete classes");
		}

		final Map<Class<? extends IBasicDataObject>,IBuilder<? extends IBasicDataObject>> mappings =
		    delegate.getMappings();

		mappings.put(IUser.class, new BuilderImpl<IUser>(UserImpl.class));
		mappings.put(IUserConnection.class, new BuilderImpl<IUserConnection>(UserConnectionImpl.class));
		mappings.put(IUserGroup.class, new BuilderImpl<IUserGroup>(GroupImpl.class));
		mappings.put(IPermissions.class, new BuilderImpl<IPermissions>(PermissionsImpl.class));
		mappings.put(IEMail.class, new BuilderImpl<IEMail>(EMailImpl.class));
		mappings.put(IOrganization.class, new BuilderImpl<IOrganization>(OrganizationImpl.class));
		mappings.put(IEMail.class, new BuilderImpl<IEMail>(EMailImpl.class));
		mappings.put(IGeoLocation.class, new BuilderImpl<IGeoLocation>(GeoLocationImpl.class));
		mappings.put(ILocation.class, new BuilderImpl<ILocation>(LocationImpl.class));
		mappings.put(IPerson.class, new BuilderImpl<IPerson>(PersonImpl.class));
		mappings.put(IPhone.class, new BuilderImpl<IPhone>(PhoneImpl.class));
		mappings.put(IUri.class, new BuilderImpl<IUri>(UriImpl.class));
		mappings.put(IImageData.class, new BuilderImpl<IImageData>(ImageDataImpl.class));
		mappings.put(IDocumentCategory.class, new BuilderImpl<IDocumentCategory>(
		    DocumentCategoryImpl.class));
		mappings.put(IDocument.class, new BuilderImpl<IDocument>(DocumentImpl.class));
		mappings.put(IDocumentVersion.class, new BuilderImpl<IDocumentVersion>(
		    DocumentVersionImpl.class));
		mappings.put(IContentInfo.class, new BuilderImpl<IContentInfo>(ContentInfoImpl.class));
		mappings.put(ITemplateCategory.class, new BuilderImpl<ITemplateCategory>(
		    TemplateCategoryImpl.class));
		mappings.put(ITemplate.class, new BuilderImpl<ITemplate>(TemplateImpl.class));
		mappings.put(ITemplateVersion.class, new BuilderImpl<ITemplateVersion>(
		    TemplateVersionImpl.class));
		mappings.put(IAccessControlEntry.class, new BuilderImpl<IAccessControlEntry>(
		    AccessControlEntryImpl.class));
		mappings.put(IAccessControlList.class, new BuilderImpl<IAccessControlList>(
		    AccessControlListImpl.class));
		mappings.put(ISecuredObjectIdentifier.class, new BuilderImpl<ISecuredObjectIdentifier>(
		    SecuredObjectIdentifierImpl.class));
		mappings.put(ISecurityIdentifier.class, new BuilderImpl<ISecurityIdentifier>(
		    SecurityIdentifierImpl.class));
		mappings.put(IOwnerDetails.class, new BuilderImpl<IOwnerDetails>(OwnerDetailsImpl.class));
		mappings.put(IApplicationSettings.class, new BuilderImpl<IApplicationSettings>(
		    ApplicationSettingsImpl.class));
		mappings.put(IUserSession.class, new BuilderImpl<IUserSession>(UserSessionImpl.class));
		mappings.put(IGenericPropertiesMap.class, new BuilderImpl<IGenericPropertiesMap>(
		    GenericPropertiesMapImpl.class));
		mappings.put(IGenericProperty.class, new BuilderImpl<IGenericProperty>(
		    GenericPropertyImpl.class));
	}

	/**
	 * Gets the mappings.
	 * @return the mappings
	 */
	protected Map<Class<? extends IBasicDataObject>,IBuilder<? extends IBasicDataObject>> getMappings() {
		return delegate.getMappings();
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.util.IObjectFactory#getEntityClass(java.io.Serializable)
	 */
	@Override
	public <E extends IBasicDataObject> Class<? extends IBasicDataObject> getEntityClass(
	    final E entity) {
		return delegate.getEntityClass(entity);
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.util.IObjectFactory#create(java.lang.Class)
	 */
	@Override
	public <E extends IBasicDataObject> E create(final Class<E> clz) throws InstantiationException {
		return delegate.create(clz);
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.util.IObjectFactory#getBuilder(java.lang.Class)
	 */
	@Override
	public <E extends IBasicDataObject> IBuilder<E> getBuilder(final Class<E> clz) {
		return delegate.getBuilder(clz);
	}
}
